package com.xuzhiguang.lightnat.server.api.controller;

import com.xuzhiguang.lightnat.server.api.domain.*;
import com.xuzhiguang.lightnat.server.core.client.ProxyTypeEnum;
import com.xuzhiguang.lightnat.server.core.exception.NatClientNotFoundException;
import com.xuzhiguang.lightnat.server.core.exception.NatProxyNotFoundException;
import com.xuzhiguang.lightnat.server.wrap.bean.Proxy;
import com.xuzhiguang.lightnat.server.wrap.manager.NatClientManager;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.stream.Collectors;

@Validated
@RestController
@RequestMapping("/api/proxy")
public class ProxyController {

    private final NatClientManager natClientManager;

    @Autowired
    public ProxyController(NatClientManager natClientManager) {
        this.natClientManager = natClientManager;
    }

    @GetMapping("/list")
    public ApiResponse<ProxyListResponse> list(@NotNull @RequestParam Long clientId) throws NatClientNotFoundException {

        List<Proxy> list = natClientManager.listProxyByClientId(clientId);

        List<ProxyListResponse.Item> items = list.stream().map(proxy -> {
            ProxyListResponse.Item item = new ProxyListResponse.Item();
            BeanUtils.copyProperties(proxy, item);
            item.setProxyType(proxy.getProxyType().name());
            item.setId(proxy.getId().toString());
            return item;
        }).collect(Collectors.toList());

        ProxyListResponse response = new ProxyListResponse();
        response.setList(items);
        return new ApiResponse<>(ResponseEnum.SUCCESS, response);
    }

    @PostMapping("/add")
    public ApiResponse<Object> add(@Valid @RequestBody ProxyAddRequest request) throws NatClientNotFoundException {

        ProxyTypeEnum proxyTypeEnum = ProxyTypeEnum.findByName(request.getProxyType());

        if (proxyTypeEnum == null) {
            return new ApiResponse<>(ResponseEnum.PARAMETERS_VALIDATE_ERROR.getCode(),
                    "proxy_type '" + request.getProxyType() + "' not found", null);
        }

        Proxy proxy = new Proxy();
        proxy.setProxyType(proxyTypeEnum);
        BeanUtils.copyProperties(request, proxy);

        proxy = natClientManager.addProxy(proxy);

        ProxyAddResponse response = new ProxyAddResponse();
        BeanUtils.copyProperties(proxy, response);

        return new ApiResponse<>(ResponseEnum.SUCCESS, response);
    }

    @PostMapping("/{proxyId}/modify")
    public ApiResponse<Object> modify(@Valid @RequestBody ProxyModifyRequest request, @PathVariable("proxyId") long proxyId) throws NatProxyNotFoundException {
        ProxyTypeEnum proxyTypeEnum = ProxyTypeEnum.findByName(request.getProxyType());

        if (proxyTypeEnum == null) {
            return new ApiResponse<>(ResponseEnum.PARAMETERS_VALIDATE_ERROR.getCode(),
                    "proxy_type '" + request.getProxyType() + "' not found", null);
        }

        Proxy proxy = new Proxy();
        proxy.setId(proxyId);
        proxy.setProxyType(proxyTypeEnum);
        BeanUtils.copyProperties(request, proxy);

        natClientManager.modifyProxy(proxy);
        return new ApiResponse<>(ResponseEnum.SUCCESS);
    }

    @DeleteMapping("/{proxyId}")
    public ApiResponse<Object> delete(@PathVariable("proxyId") long proxyId) {


        natClientManager.deleteProxy(proxyId);
        return new ApiResponse<>(ResponseEnum.SUCCESS);
    }

}
